package http

import (
	"github.com/edgexfoundry/edgex-go/internal/app/core/metadata/application"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos/requests"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos/responses"
	metadataContainer "github.com/edgexfoundry/edgex-go/internal/core/metadata/container"
	"github.com/edgexfoundry/edgex-go/internal/io"
	"github.com/edgexfoundry/edgex-go/internal/pkg"
	"github.com/edgexfoundry/edgex-go/internal/pkg/utils"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/container"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/di"
	commonDTO "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/common"
	"github.com/gorilla/mux"
	"math"
	"net/http"
)

type ProductAttributeController struct {
	reader io.DtoReader
	dic    *di.Container
}

func NewProductAttributeController(dic *di.Container) *ProductAttributeController {
	return &ProductAttributeController{
		reader: io.NewJsonDtoReader(),
		dic:    dic,
	}
}

func (pac *ProductAttributeController) AddProductAttribute(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer func() { _ = r.Body.Close() }()
	}

	lc := container.LoggingClientFrom(pac.dic.Get)
	ctx := r.Context()

	var reqDTO requests.AddProductAttributeRequest
	err := pac.reader.Read(r.Body, &reqDTO)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}
	productAttribute := requests.AddProductAttributeReqToProductAttributeModel(reqDTO)
	newId, err := application.AddProductAttribute(productAttribute, ctx, pac.dic)
	var response interface{}
	if err != nil {
		response = commonDTO.NewBaseResponse(
			reqDTO.RequestId,
			err.Message(),
			err.Code())
	} else {
		response = commonDTO.NewBaseWithIdResponse(
			reqDTO.RequestId,
			"",
			http.StatusCreated,
			newId)
	}

	utils.WriteHttpHeader(w, ctx, http.StatusOK)
	pkg.EncodeAndWriteResponse(response, w, lc)
}

func (pac *ProductAttributeController) AttributesByProductId(w http.ResponseWriter, r *http.Request) {
	lc := container.LoggingClientFrom(pac.dic.Get)
	ctx := r.Context()
	config := metadataContainer.ConfigurationFrom(pac.dic.Get)

	vars := mux.Vars(r)
	productId := vars["productid"]

	offset, limit, _, err := utils.ParseGetAllObjectsRequestQueryString(r, 0, math.MaxInt32, -1, config.Service.MaxResultCount)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}
	productAttributes, totalCount, err := application.AttributesByProductId(offset, limit, productId, pac.dic)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}
	response := responses.NewMultiProductAttributesResponse("", "", http.StatusOK, totalCount, productAttributes)
	utils.WriteHttpHeader(w, ctx, http.StatusOK)
	pkg.EncodeAndWriteResponse(response, w, lc)
}

func (pac *ProductAttributeController) ProductAttributeDelete(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer func() { _ = r.Body.Close() }()
	}

	lc := container.LoggingClientFrom(pac.dic.Get)
	ctx := r.Context()
	//correlationId := correlation.FromContext(ctx)
	var reqDTOs []string
	err := pac.reader.Read(r.Body, &reqDTOs)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}

	err = application.ProductAttributeDelete(reqDTOs, pac.dic)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}
	response := commonDTO.NewBaseResponse("", "", http.StatusOK)
	utils.WriteHttpHeader(w, ctx, http.StatusOK)
	pkg.EncodeAndWriteResponse(response, w, lc)
}

func (pac *ProductAttributeController) UpdateProductAttribute(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer func() { _ = r.Body.Close() }()
	}

	lc := container.LoggingClientFrom(pac.dic.Get)
	ctx := r.Context()

	var reqDTOs requests.UpdateProductAttributeRequest
	err := pac.reader.Read(r.Body, &reqDTOs)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}
	productAttribute := requests.UpdateAttributeReqToAttributeModel(reqDTOs)
	edgeXerr := application.UpdateProductAttribute(productAttribute, pac.dic)

	if edgeXerr != nil {
		utils.WriteErrorResponse(w, ctx, lc, edgeXerr, "")
		return
	}
	response := commonDTO.NewBaseResponse("", "", http.StatusOK)
	utils.WriteHttpHeader(w, ctx, http.StatusOK)
	pkg.EncodeAndWriteResponse(response, w, lc)
}
